package payfun

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"math/rand"
	"reflect"
	"sort"
	"strings"
	"time"
)

func isEmptyValue(v interface{}) bool {
	// Check for nil or zero-value equivalent for the type of v.
	switch v.(type) {
	case string:
		return v == ""
	case nil:
		return true
	default:
		return reflect.ValueOf(v).IsZero()
	}
}

func GenerateSignature(params map[string]any, secret string) (string, error) {
	var sortedKeys []string
	for k := range params {
		sortedKeys = append(sortedKeys, k)
	}
	sort.Strings(sortedKeys)

	var sortedParamStrBuilder strings.Builder
	for _, k := range sortedKeys {
		val := params[k]
		if k != "sign" && !isEmptyValue(val) { // Exclude empty or zero-value fields
			sortedParamStrBuilder.WriteString(k)
			sortedParamStrBuilder.WriteString("=")
			sortedParamStrBuilder.WriteString(fmt.Sprintf("%v", val)) // Convert any type to string
			sortedParamStrBuilder.WriteString("&")
		}
	}

	// Remove the last "&"
	sortedParamStr := sortedParamStrBuilder.String()
	sortedParamStr = sortedParamStr[:len(sortedParamStr)-1]

	// Append the secret and create the final string to be hashed
	finalStr := sortedParamStr + "&secret=" + secret

	// Generate and uppercase the MD5 hash
	hasher := md5.New()
	_, err := hasher.Write([]byte(finalStr))
	if err != nil {
		return "", err
	}
	signature := strings.ToUpper(hex.EncodeToString(hasher.Sum(nil)))

	return signature, nil
}

// UniqueRandomString 生成一个指定长度的不重复随机字符串
func UniqueRandomString(length int) (string, error) {
	const chars = "abcdefghijklmnopqrstuvwxyz0123456789"
	charSetLength := len(chars)
	if length > charSetLength {
		return "", fmt.Errorf("requested length exceeds character set size")
	}

	rand.Seed(time.Now().UnixNano())

	result := make([]byte, length)
	seen := make(map[byte]bool)

	for i := 0; i < length; i++ {
		var char byte
		for {
			char = chars[rand.Intn(charSetLength)]
			if !seen[char] {
				seen[char] = true
				break
			}
		}
		result[i] = char
	}

	return string(result), nil
}
